home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Tele / C / Comet2.1.3.cpt / Comet / main.c < prev    next >
Text File  |  1991-10-22  |  39KB  |  1,824 lines

  1. /*
  2.     Copyright Cornell University 1986.  All rights are reserved.
  3. */
  4.  
  5.  
  6. /***************************************************************************
  7. **     3270 Driver  initializations, main program, & error handler        **
  8. ****************************************************************************
  9. **     Developed at Cornell University by:                                  **
  10. **     Richard Cogger, Peter Hoyt, Kevin Saunders, & John Lynn              **
  11. **     includes calls to TCP, IP, and tasking routines developed at MIT   **
  12. ***************************************************************************/
  13.  
  14. /* tn3270.c contains the main() loop and various support routines */
  15.  
  16. #ifdef MULTI
  17.             /* multiple windows version */
  18.             
  19. #include    <em.h>
  20.  
  21. #include    <cntl.h>
  22. #include    <key.h>
  23. #include    <macdefs.h>
  24. #include    <h19.h>
  25. #include    <timer.h>
  26. #include    <ft.h>
  27.  
  28. #include    <3270.h>                       /* external variables & constants     */
  29. #include    <cntldefs.h>
  30. #include    <resdefs.h>
  31. #include    "xlate.h"
  32. #include    "menudefs.h"
  33. #include    "tftp.h"
  34.  
  35. #ifdef DUALTCP
  36.  
  37. #include    <net.h>        /* NEW merged TCP drags in task.h */
  38. #else
  39.  
  40. #include    <net.h>        /* NEW merged TCP drags in task.h */
  41. #include    <q.h>        /* TODO should be different with MACTCP alone */
  42. extern char timertripped;        /* the timer requires service */
  43. #endif
  44.  
  45. #else
  46.  
  47. #ifdef MACTCP
  48. #include    <q.h>
  49. #else
  50. #include    <tcp.h>
  51.  
  52. #endif
  53.  
  54. #include    <stdio.h>
  55.  
  56. #include    <osutil.h>
  57. #include    <quickdraw.h> 
  58. #include    <resource.h> 
  59. #include    <toolutil.h>
  60. #include    <window.h>
  61. #include    <control.h>
  62. #include    <font.h> 
  63. #include    <event.h>
  64. #include    <desk.h>
  65. #include    <packages.h>
  66. #include    <segment.h>
  67.  
  68. #include    <menu.h>
  69. #include    <dialog.h>
  70. #include    <memory.h>
  71.  
  72. #include    <cntl.h>
  73. #include    <key.h>
  74. #include    <macdefs.h>
  75. #include    <h19.h>
  76. #include    <timer.h>
  77. #include    <emdefs.h>
  78. #include    <telnet.h>
  79. #include    <ft.h>
  80.  
  81. #include    <3270.h>                       /* external variables & constants     */
  82. #include    <cntldefs.h>
  83. #include    <resdefs.h>
  84. #include    "xlate.h"
  85. #include    "menudefs.h"
  86. #include    "tftp.h"
  87.  
  88. #endif
  89.  
  90.  
  91.  
  92. #ifdef DUALTCP
  93. #undef MACTCP
  94. /* make both tcps in one package */
  95. #endif
  96.  
  97.  
  98. struct winds * conns[MAXWIND];
  99. short conncount;
  100.  
  101. /* true globals */
  102.  
  103. #ifdef MULTI
  104. struct winds * emdp;            /* pointer to connection block we're using */
  105. struct winds * keydp;            /* pointer to top window connection block we're using */
  106. #endif
  107.  
  108. short mfbackonly;                /* run whole app only in background */
  109.  
  110. WindowPtr    keywindow;            /* the active window, emwindow or textwindow */ 
  111. WindowPtr    iconwindow;            /* top go-away window, shows tn3270 icon */
  112. WindowPtr    emwindow;            /* the current output emulator window */ 
  113.  
  114. #ifdef USEHELPWINDOW
  115. /* help window vars */
  116. WindowPtr    helpwindow;            /* there is one help window */ 
  117. struct windtext helptext;
  118. struct windtext {
  119.     TEHandle    texthand;                /* with a TextEdit box and a scrollbar */ 
  120.     int            FirstLine;                /* the number of the line at the top */
  121.     short         textscrapped;            /* the TE scrap has been touched and must be coerced */
  122.     short         textlines;                /* # of lines in page */
  123.     ControlHandle scrollhand;            /* scroll bar control */
  124. }
  125. #endif
  126.  
  127. EventRecord    myEvent;
  128.  
  129. short courierprint;                    /* print using Courier on LaserWriters? */
  130. short appresfid;                    /* application resource file descriptor */
  131. short appvol;                        /* application home volume */
  132. long appdir;                        /* application home directory */
  133. short appvref;                        /* application volume ref num */
  134.  
  135. char * setfile = "\PComet Default";            /* system folder settings default filename */
  136.  
  137. short quitonclose;                    /* user wants app to close when no windows */
  138.  
  139. /* connection management */
  140. short connavailable;            /* an empty connection struct is lying about */
  141.  
  142. /* TCP vars */
  143. short cutcpopen;                /* Cornell TCP has been opened */
  144. short macipopen;                /* macTCP has been opened */
  145. short mactcpopen;                /* macTCP has been opened */
  146. short mtevent;                    /* MacTCP--new data or control info has arrived */
  147.  
  148. short mtcpsendasync;            /* use async send w/ MacTCP */
  149.  
  150. short tftpopen;                    /* has tftp been initialized? */
  151. short tftpserve;                /* act as a tftp server */
  152. short tftpask;                    /* query user about transfers */
  153.  
  154. short trydsdraw;                /* *try* to use direct to screen drawing */
  155. short riskydsdraw;                /* only use dsdraw in FrontWindow() */
  156.  
  157. PicHandle shrinkpict;            /* picture for shrink control */
  158. PicHandle tapepict;                /* picture of cassette tape */
  159.  
  160. short icon_up;                    /* iconwindow is up for top window */
  161.  
  162. long long1;                        /* useful storage for assembly routines */
  163. long long2;
  164. long long3;
  165. long long4;
  166.  
  167. TEHandle helptehand;
  168. WindowPtr helpwind;
  169. long filltimeout;
  170.  
  171. /* mouserect sizing and tracking of cursor */
  172.  
  173. short  trackon;                    /* flag for cursor tracking on */
  174. Rect mouserect;                    /* also used by h19curset to find the targeted x,y */
  175. short inemulator;                /* an emulator is in use */
  176. short clickdelay = 10;            /* # of ticks to wait before setting a selection */
  177.  
  178. /* Cursors */
  179.  
  180. Rect    cursrect;                /* inviolable cursor Rect */
  181. short    curson;                    /* cursor state on or off */
  182. Cursor    blank = { 
  183.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  184.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  185.     8, 8 };
  186. Cursor * thecursor = ␣
  187. Rect    zaprect;                /* for ShieldCursor */
  188. SysPtr    paramptr;                /* pointer to parameters for cursor blink time */
  189. unsigned long    cursalarm;        /* tick count at which to change cursor */
  190. RgnHandle emclip;                /* holds previous em clip rect */
  191. RgnHandle q3clip;                /* for calculating new clip w/o q3 box */
  192.                                 
  193.  
  194. /* q3 control globals */
  195. short q3conth;                    /* height of quadrant 3 control button */
  196. short q3contskip;                /* size of skip every 3 buttons */
  197. Rect boxrect;                /* box in which the q3 button labels are drawn */
  198.  
  199. /* character images for direct to screen drawing */
  200.  
  201. FONTS    font;                    /* normal font */
  202. FONTS    invfont;                /* inverted */
  203. FONTS    boldfont;                /* bold font */
  204. FONTS    invboldfont;            /* inverted */
  205. FONTS    bvtfont;                /* vt font */
  206. FONTS    invbvtfont;                /* inverted */
  207.  
  208. short * chofftab9;                /* array of character offsets to avoid multiplies */
  209. short * chofftab12;                /* array of character offsets to avoid multiplies */
  210.  
  211. RgnHandle updateRgn;            /* rgn for scroll update regions */
  212.  
  213. short bkrd_act = 1;                /* is tcp running in background mode? */
  214.  
  215. Rect dragrect;                    /* the drag rectangle for all windows */
  216.  
  217. /* we use a bit array to mark dirty lines a` la zapchar, here are the masks */
  218.  
  219. unsigned long modmask[32] = {
  220.     0x00000001L,
  221.     0x00000002L,
  222.     0x00000004L,
  223.     0x00000008L,
  224.     0x00000010L,
  225.     0x00000020L,
  226.     0x00000040L,
  227.     0x00000080L,
  228.     0x00000100L,
  229.     0x00000200L,
  230.     0x00000400L,
  231.     0x00000800L,
  232.     0x00001000L,
  233.     0x00002000L,
  234.     0x00004000L,
  235.     0x00008000L,
  236.     0x00010000L,
  237.     0x00020000L,
  238.     0x00040000L,
  239.     0x00080000L,
  240.     0x00100000L,
  241.     0x00200000L,
  242.     0x00400000L,
  243.     0x00800000L,
  244.     0x01000000L,
  245.     0x02000000L,
  246.     0x04000000L,
  247.     0x08000000L,
  248.     0x10000000L,
  249.     0x20000000L,
  250.     0x40000000L,
  251.     0x80000000L
  252. };
  253.  
  254. char zapuline;                    /* flag to zapchar to underline character */
  255. char zapinvert;                    /* flag to zapchar to underline character */
  256.  
  257. char inselection;                /* flag that we are in selection range */
  258.  
  259. char skiparr[NOCHARS];            /* chars which are blank & can be skipped */
  260. char allskiparr[NOCHARS];        /* alternate all-TRUE skiparr */
  261.  
  262. short keyboard = PLUSKEYBOARD;    /* keyboard type */
  263. short keypadswitch;                /* switch SE keypad */
  264.  
  265. /* a default ibmcolormap */
  266.  
  267. struct ibmcolormap ibmcolormap = {
  268.                                                 /* unprotected ... */
  269.     0, 0, 0,             65535, 65535, 65535,    /* normal (black on white) */
  270.     50000, 1000, 1000,     65535, 65535, 65535,    /* sense (red on white) */
  271.     0, 0, 0,             65535, 65535, 65535,    /* intense (black on white) */
  272.     0, 0, 0,             65535, 65535, 65535,    /* invis (black on white) */
  273.  
  274.                                                 /* protected ... */
  275.     0, 0, 0,             65535, 65535, 65535,    /* normal (black on white) */
  276.     50000, 1000, 1000,     65535, 65535, 65535,    /* sense (red on white) */
  277.     0, 0, 0,            65535, 65535, 65535,    /* intense (black on white) */
  278.     0, 0, 0,             65535, 65535, 65535        /* invis (black on white) */
  279. };
  280.  
  281. struct ibmcolormap asccolormap = {
  282.     0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF,        /* normal (black on white) */
  283.     0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000,        /* reverse (white on black) */
  284.     0xFFFF, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF,        /* bold (red on white) */
  285.     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000,     /* bold reverse (white on red) */
  286.  
  287.                                                         /* blink ... */
  288.     0x0000, 0x0000, 0x0000, 0xFF70, 0xFFFF, 0x3752,     /* black on yellow */
  289.     0xFF70, 0xFFFF, 0x3752, 0x0000, 0x0000, 0x0000,     /* rev: Yellow on black */
  290.     0xFFFF, 0x0000, 0x0000, 0xFF70, 0xFFFF, 0x3752,     /* bold: red on yellow */
  291.     0xFF70, 0xFFFF, 0x3752, 0xFFFF, 0x0000, 0x0000,     /* boldrev: yellow on red */
  292. };
  293.  
  294. /* TODO ideally the strings and actions associated with the 3rd quadrant buttons
  295.     would be reconfigurable on a per-window basis... */
  296.     
  297. char * q3strings[] = {
  298.     "PF1",
  299.     "PF2",
  300.     "PF3",
  301.     "PF4",
  302.     "PF5",
  303.     "PF6",
  304.     "PF7",
  305.     "PF8",
  306.     "PF9",
  307.     "PF10",
  308.     "PF11",
  309.     "PF12",
  310.     "PF13",
  311.     "PF14",
  312.     "PF15",
  313.     "PF16",
  314.     "PF17",
  315.     "PF18",
  316.     "PF19",
  317.     "PF20",
  318.     "PF21",
  319.     "PF22",
  320.     "PF23",
  321.     "PF24",
  322.     
  323.     /* VT52/VT100 labels */
  324.     "KP 1",
  325.     "KP 2",
  326.     "KP 3",
  327.     "KP 4",
  328.     "KP 5",
  329.     "KP 6",
  330.     "KP 7",
  331.     "KP 8",
  332.     "KP 9",
  333.     "KP 0",
  334.     "KP -",
  335.     "KP , (+)",
  336.     
  337.     "PF1 (Gold)",
  338.     "PF2 (Help)",
  339.     "PF3",
  340.     "PF4",
  341.     "KP .",
  342.     "KP Enter",
  343.     "Find",
  344.     "Insert Here",
  345.     "Remove",
  346.     "Select",
  347.     "Prev Screen",
  348.     "Next Screen"
  349. };
  350.     
  351. /* for ASCII vt100 mode */
  352.             
  353. char q3vtcontrols[] = {
  354. 'q',
  355. 'r',
  356. 's',
  357. 't',
  358. 'u',
  359. 'v',
  360. 'w',
  361. 'x',
  362. 'y',
  363. 'p',
  364. 'm',
  365. 'l',
  366.  
  367. 'P',
  368. 'Q',
  369. 'R',
  370. 'S',
  371. 'n',
  372. 'M',
  373. '1',
  374. '2',
  375. '3',
  376. '4',
  377. '5',
  378. '6'
  379. };
  380.  
  381. /* for ASCII mode */
  382.             
  383. char q3controls[] = {
  384. 'S',
  385. 'T',
  386. 'U',
  387. 'V',
  388. 'W',
  389. 'X',
  390. 'Y',
  391. 'Z',
  392. '[',
  393. 'P',
  394. 'Q',
  395. 'R'
  396. };
  397.  
  398. char * nosessionstr = "Session closed";
  399. char * hostwait = "Connecting to host...";
  400. char * badaddress = "Invalid host address";
  401.  
  402.  
  403. /* BIGG preserve as globals for better speed */
  404.  
  405. /* shared BIGG */
  406.  
  407. /* used by dsdraw zap.asm routines */
  408.  
  409. FONTS *thefont;                    /* BIGG */
  410. short xpos, ypos;                /* BIGG current x, y position */
  411. unsigned long modflg;            /* BIGG line modified bit array */
  412. unsigned long clrflg;            /* BIGG line cleared bit array */
  413. short fontwidth;                /* BIGG width of font */
  414. short ** startarr;                /* BIGG dsdraw -> array of ptrs to scanline starts */
  415. short screenbytes;                /* BIGG width of screen in bytes */
  416. short screenrem;                /* BIGG screenbytes - std screen */
  417. char * skiptest;                /* current skip array to use in zap */
  418.     
  419. /* h19 BIGG */
  420. short mode;                        /* BIGG interpretation mode of emulator */
  421. unsigned char * charp;            /* BIGG cursor loc for these arrays */
  422. short inserton;                    /* BIGG insert mode */
  423. short linelength;                /* BIGG width of row */
  424. short lastcol;                    /* BIGG linelength - 1 */
  425. unsigned char attrib;            /* BIGG normal/reverse mode for copy drawing */
  426.  
  427. short wrap_around;                /* BIGG wrap at end of line if true */
  428.  
  429. /* vt100 BIGG */
  430.  
  431. short vtmode;                    /* BIGG new mode holder for vt100 */
  432. unsigned short * argp;            /* BIGG -> current argument */
  433.  
  434. /* 3270 BIGG */
  435. short cmdstate;                    /* BIGG state of the emulator */
  436. unsigned char *scr_map;            /* BIGG screen map */
  437. unsigned char *smap_end;        /* BIGG end of map */
  438. unsigned char *current_attr;    /* BIGG pointer to most recent attribute */
  439. unsigned char *cursor_ptr;        /* BIGG current cursor position in screen map */
  440. unsigned char * firstp;            /* BIGG ptr to first data byte processed for set_map */
  441.  
  442.  
  443.  
  444.  
  445. /* end BIGG vars */
  446.  
  447.  
  448.  
  449. #ifdef MACTCP
  450. unsigned NDEBUG = TRUE;                /* stupid debug flag */
  451. struct net thisnet;
  452. struct net * rnet;
  453. short nnrup;                        /* network not responding dialog up */
  454. struct task * tk_cur;                    /* subs for current task ptr */
  455. short iplog;
  456.  
  457. extern int tcpwr_usr();            /* these are now stubs for compatibility */
  458. extern int tcpmst_run();
  459. extern int tcpopn_usr();
  460. extern int tcpcls_usr();
  461. extern int tcptmo_usr();
  462. extern int tcppr_dot();
  463. extern int tcpbfr();
  464.  
  465. #else
  466.  
  467. extern int tcpwr_usr();
  468. extern int tcpmst_run();
  469. extern int tcpopn_usr();
  470. extern int tcpcls_usr();
  471. extern int tcptmo_usr();
  472. extern int tcppr_dot();
  473. extern int tcpbfr();
  474. #endif
  475.  
  476.  
  477. unsigned long tickserial;    /* next tick count to service serial port */
  478. short serialwait;            /* how long the serial mgr thinks we should wait */
  479. unsigned long tickcursor;    /* next tick count to service cursor */
  480. unsigned long tickstats;    /* next tick count to display packet counters */
  481. extern short modaldialog;
  482.  
  483.  
  484. int proc_token();
  485. int nullputchar();
  486. int nullputflush();
  487.  
  488. short edresetselect;            /* reset selection after emulator edit action */
  489.  
  490. char isdiacritic[NOCHARS];    /* marks 0-width diacritical characters for screen drawing */
  491.  
  492.  
  493. /* NEW CU TCP/ MacTCP merge features */
  494.  
  495. struct winds * tcpemdp;        /* the window context in which CU tcp runs */
  496.  
  497.  
  498.  
  499. #ifdef KEEPALIVE
  500.  
  501. timer *tel_ayt;
  502. #define AYTT 500       /* seconds between ayt tickles */
  503. extern int            beep_ayt();
  504.  
  505. #endif
  506.  
  507.  
  508.  
  509.  
  510. main()
  511. {
  512. #ifdef MACTCP
  513.     rnet = &thisnet;
  514. #else
  515. #asm
  516.     public _appstak
  517.     move.l a6,_appstak ;    /* set the stack bottom ptr to copy the whole stack */
  518. #endasm
  519. #endif
  520.  
  521.     A5init();                    /* save a5 */
  522.     macinit((long) (75L * 1024L));
  523.     setupapplemenu();        /* so we can chk for multifinder */
  524.     if (chkmultifinder()) {
  525.         EventRecord myEvent;
  526.         
  527.         /* eventavail will put these back on the queue, but not just any event! */
  528.         EventAvail(keyDownMask, &myEvent);
  529.         EventAvail(keyDownMask, &myEvent);
  530.         EventAvail(keyDownMask, &myEvent);
  531.             /* these calls will prompt the MultiFinder to display our startup screen */
  532.     }
  533.     if (!scrinit()) {
  534.         error("Can't initialize screen");
  535.         cu_exit(-1);
  536.     }
  537.  
  538.     tn_init();
  539.     ibm_init();
  540.     setupmenu();
  541.  
  542.     SetEventMask(everyEvent);
  543.         /* fix event mask for autokeycommand--may cause full event queue! */
  544.  
  545. #ifdef DOHYC
  546.     hyc_init();
  547. #endif
  548.  
  549. /* and some optional stuff */
  550.  
  551. #ifdef KEEPALIVE
  552.     if ((tel_ayt = tm_alloc()) == NULL) {
  553.         error("Unable to allocate telnet ayt timer");
  554.         cu_exit(-1);
  555.     }
  556.     tm_set(AYTT, beep_ayt, NULL, tel_ayt);
  557. #endif
  558.  
  559. #ifdef MACTCP
  560.     tk_cur = 2L;                /* needs to be nonzero so tk_yield will be called */
  561.     tm_init();
  562. #else
  563.     /* initialize tasking */
  564.     tk_init(10000);                /* size of the main task's stack */
  565.     tm_init();
  566. #endif
  567.  
  568.     /* open document files & do configuration  */
  569.     openlaunchres();    
  570.     
  571.     fillwindclose();
  572.         /* close the copyright window if it's up */
  573.  
  574. #ifdef TFTPSERVE
  575.     /* start the tftp server and turn it on if configured on */
  576.     if (tftpserve == TFYES) {
  577.         tfs_on();
  578.     }
  579. #endif
  580.     /* and now we run ... */
  581.     while (TRUE) {
  582.         
  583.         user_act();            /* user input--process mac events */
  584.  
  585.         token_service();    /* user output--handle actions waiting on the queue */
  586.         io_service();        /* for merged MacTCP/CUTCP */
  587.         screen_service();    /* update screen */
  588.  
  589. #ifdef DUALTCP
  590.         tk_yield();            /* task yield for Cornell TCP */
  591. #else
  592.         if (timertripped)
  593.             tm_main();        /* service timer */
  594. #endif
  595.     }
  596.     /* not reached */
  597.     cu_exit(0);
  598. }
  599.  
  600.  
  601. /*  some trivial subroutines that interact with lower level code  */
  602.  
  603. #ifdef KEEPALIVE
  604.  
  605. /*  set a flag when timer pops (should just send an AYT!) */
  606.  
  607. beep_ayt() 
  608.     emdp->event_reg |= TICKLE;
  609. }
  610.  
  611. #endif
  612.  
  613. /* figure out a neat telnet socket */
  614.  
  615. tn_sock() 
  616. {
  617.     long temp;
  618.  
  619.     GetDateTime(&temp);
  620.     temp &= 0xffff; 
  621.     if (temp < 1000) 
  622.         temp += 1000;
  623.     return((unsigned) temp);
  624. }
  625.  
  626.  
  627. /* called when a connection is opened to perform UI tasks */
  628.  
  629. opn_usr() 
  630. {
  631.     emdp->connopen = TRUE;
  632.  
  633.     emdp->hycconnwait = FALSE;
  634.     if (emdp->emwindow != NULL) {
  635.         /* update the menus; first the window menu mark */
  636.         if (emdp->conntype == CONN_MACTCP || emdp->conntype == CONN_CUTCP) {
  637.             windmenumark(emdp, 0xA5);        /* set a • mark */
  638.         }
  639.         else if (emdp->conntype == CONN_SERD) {
  640.             windmenumark(emdp, emdp->usebport ? '-' : '+');        
  641.                 /* set a mark on the menu item + for modem port,
  642.                     - for printer port */
  643.         }
  644.         else if (emdp->conntype == CONN_COMMMGR) {
  645.             windmenumark(emdp, 0xA5);        /* set a • mark */
  646.         }
  647.         
  648.         if (keydp == NULL || emwindow == keydp->emwindow) {
  649.             if (setmsession(emdp) || setmenuconn(emdp))
  650.                 DrawMenuBar();
  651.         }
  652.         restore25();    /* allow controls to be drawn */
  653.     }
  654. }
  655.  
  656.  
  657. /* called when a session is closed, window menu mark already set */
  658. /* WARNING: twp may disappear, emdp may change! */
  659.  
  660.  
  661. cls_usr() 
  662. {
  663.     if (!emdp->connopen)
  664.         return;
  665.         
  666.     if (emdp->hycactive)
  667.         emdp->hycconnwait = FALSE;
  668.  
  669.     emdp->connopen = FALSE;
  670.     emdp->termset = FALSE;            /* no terminal type selected */
  671.     emdp->event_reg = 0;
  672.     emdp->in_cnt = 0;
  673.     emdp->out_cnt = 0;
  674.     flushactions(emdp);
  675.     
  676.     savescreen();            /* in case we're logging the session */
  677.     logclose();
  678.     
  679.     if (emdp->emwindow != NULL) {
  680.         
  681.         if (!line25on(emdp))
  682.             pr25(0, nosessionstr);
  683.         status_info();
  684.         /* prettywind(TRUE); 
  685.             results in cleared area when color is on */
  686.         if (keydp == NULL || emdp->emwindow == keydp->emwindow) {
  687.             /* fix menu to reflect status */
  688.             if (setmsession(emdp) || setmenuconn(emdp))
  689.                 DrawMenuBar();
  690.         }
  691.         if (emdp->disposeonclose) {
  692.             /* kill window when closed */
  693.             queryclosewind(emdp);
  694.         }
  695.     }
  696. }
  697.  
  698. tcpmst_run()
  699. {
  700. }
  701.  
  702.  
  703. /* call wr_usr after getting the context */
  704.  
  705. tcpwr_usr(buf, len, urg)
  706. unsigned char *buf;
  707. int len;
  708. int urg; 
  709. {
  710.     struct winds * oemdp;
  711.     
  712.     oemdp = emdp;
  713.     getcontext(tcpemdp);
  714.     wr_usr(buf, len, urg);
  715.     
  716.     if (emdp == oemdp)
  717.         emdp->modflg = modflg;
  718.         /* needs to be updated even if no context change so screen_service can
  719.             pick up the changes */
  720.     else
  721.         getcontext(oemdp);
  722. }
  723.  
  724. /* call opn_usr after getting the context */
  725.  
  726. tcpopn_usr()
  727. {
  728.     struct winds * oemdp;
  729.     
  730.     oemdp = emdp;
  731.     getcontext(tcpemdp);
  732.     opn_usr();
  733.     getcontext(oemdp);
  734. }
  735.  
  736. /* call cls_usr after getting the context */
  737.  
  738. tcpcls_usr()
  739. {
  740.     struct winds * oemdp;
  741.     
  742.     tcpemdp->closeflag = TRUE;
  743.     mtevent = TRUE;
  744. }
  745.  
  746.  
  747. /* make a new connection, do user dialog to configure it, and connect */
  748.  
  749. newconn()
  750. {
  751.     if (makeconn())
  752.         return(-1);
  753.  
  754.     opensettings();
  755.     getconfig();                /* do first, namewindow response may override */
  756.     releaseconfig();            /* release handles, which we don't want to use */
  757.     
  758.     if (namewindow()) {
  759.         closesettings();
  760.         killconn();
  761.         return(-1);
  762.     }
  763.  
  764.     emdp->newconf = TRUE;        
  765.         /* it's a new, unopened file even if "Untitled" unchanged */
  766.  
  767.     setappfilename();
  768.     
  769.     if (makewind()) {
  770.         closesettings();
  771.         killconn();
  772.         return(-1);
  773.     }
  774.     
  775.     emdp->resfid = 0;
  776.     setwindvols(emdp);            /* set default directories */
  777.     
  778.     closesettings();
  779.  
  780.     emdp->keyxhead = NULL;        /* don't inherit key resources */
  781.  
  782.     restore25();
  783.     addwindmenu(emdp->emwindow);
  784.  
  785.     openconn(emdp);
  786.     
  787.     return(0);
  788. }
  789.  
  790.  
  791. /* make a new connection structure, initialize vt100 */
  792.     
  793. makeconn()
  794. {
  795.     struct winds * otwp;
  796.     struct timer * otimer;
  797.     
  798.     if (conncount >= MAXWIND)
  799.         return(-1);
  800.  
  801.     if (connavailable) {
  802.         /* emdp is the only connection block lying around,
  803.             no window, no connection */
  804.         connavailable = FALSE;
  805.         emedit(emdp, TRUE);
  806.         
  807.         /* save things from the old structure */
  808.         otimer = emdp->token_tm;
  809.         memzero(emdp, sizeof(struct winds));
  810.             /* zero out the new structure */
  811.         emdp->token_tm = otimer;
  812.     }
  813.     else {
  814.         if (!memtest((long) sizeof(struct winds), "to make session")) {
  815.             return(-1);
  816.         }
  817.         otwp = emdp;
  818.         savecontext(emdp);
  819.         emdp = NewPtr((Size) (sizeof(struct winds))); 
  820.         if (emdp == NULL) {
  821.             emdp = otwp;
  822.             return(-1);
  823.         }
  824.         memzero(emdp, sizeof(struct winds));    
  825.             /* zero out the new structure */
  826.         
  827.         setcontext(emdp);
  828.  
  829.         if ((emdp->token_tm = tm_alloc()) == NULL) {
  830.             DisposPtr(emdp);
  831.             getcontext(otwp);
  832.             return(-1);
  833.         }
  834.     }
  835.     
  836.     emdp->emwindow = (WindowPtr) NULL;
  837.     emdp->iconwindow = (WindowPtr) NULL;
  838.     
  839.     emdp->savefid = 0;
  840.     emdp->gotoy = -1;
  841.  
  842.     emdp->cursorwait = TRUE;
  843.     ibmmode(FALSE);
  844.  
  845.     emdp->putchar = nullputchar;
  846.     emdp->putflush = nullputflush;
  847.     conns[conncount] = emdp;
  848.     conncount++;
  849.  
  850.     return(0);
  851.  
  852. }
  853.  
  854. /* destroy the most recent attempt to make a connection structure */
  855.  
  856. killconn()
  857. {
  858.     --conncount;
  859.     conns[conncount] = NULL;
  860.     if (keydp != NULL) {
  861.         DisposPtr(emdp);
  862.         setcontext(keydp);
  863.     }
  864.     else {
  865.         setcontext(conns[0]);
  866.     }        
  867. }
  868.  
  869.  
  870. /* standard close bottleneck call */
  871.  
  872. closeconn(twp)
  873. struct winds * twp;
  874. {
  875.     if (twp->connopen) {
  876.         getcontext(twp);
  877.         if (!hostclosemacro(twp->closemacro))
  878.             /* if there's no close macro, go ahead and close it up */
  879.             docloseconn();
  880.     }
  881. }
  882.  
  883. /* REALLY do a close on the emdp connection */
  884.  
  885. docloseconn()
  886. {
  887.     if (!emdp->connopen) {
  888.         return();
  889.     }
  890.     if (emdp->conntype == CONN_MACTCP) {
  891.         mactcp_close();
  892.     }
  893. #ifdef DUALTCP
  894.     else if (emdp->conntype == CONN_CUTCP) {
  895.         tcp_close();
  896.         emdp->ucb.u_state = CLOSING;
  897.         emdp->ucb.u_rstate = BLOCK;
  898.     }
  899. #endif
  900.     else if (emdp->conntype == CONN_SERD) {
  901.         windmenumark(emdp, noMark);        /* clear any marks */
  902.         closeserport(emdp);
  903.         cls_usr();            /* WARNING: twp may disappear, emdp may change! */
  904.     }
  905. }
  906.  
  907.  
  908. /* remove a connection from the table, we have no connection */
  909.  
  910. releaseconn(twp)
  911. struct winds * twp;
  912. {
  913.     register short count = 0;
  914.     
  915.     for (count = 0; count < conncount; count ++) {
  916.         if (twp == conns[count])
  917.             break;
  918.     }
  919.     if (count == conncount)
  920.         /* no such connection exists */
  921.         return(-1);
  922.     
  923.     /* we found a match, release resources associated with it */
  924.     if (twp->conntype == CONN_MACTCP) {
  925.         if (mactcpopen) {
  926.             tcp_release(twp);
  927.             tcpmemoryreclaim(twp);
  928.         }
  929.     }
  930. #ifdef DUALTCP
  931.     else if (twp->conntype == CONN_CUTCP) {
  932.         if (cutcpopen) {
  933.             /* TODO should we close down Cornell TCP completely to
  934.                 allow MacTCP to run? */
  935.             /* tcpemdp = NULL;        TODO this is improper! */
  936.             ;
  937.         }
  938.     }
  939. #endif
  940.     else if (twp->conntype == CONN_SERD) {
  941.         closeserport(twp);
  942.     }
  943.     
  944.     
  945.     if (conncount > 1) {
  946.         /* kill it */
  947.         
  948.         ascii_free(twp);                /* release any ASCII emulator memory */
  949.         ibm_free(twp);                /* release any IBM emulator memory */
  950.         tm_clear(twp->token_tm);
  951.         tm_free(twp->token_tm);
  952.         DisposPtr(twp);
  953.  
  954.         /* now shift down the other conns in the table */
  955.         for ( count++ ; count < conncount; count++) {
  956.             conns[count - 1] = conns[count];
  957.         }
  958.         
  959.         /* set the context to the first one */
  960.         if (twp == emdp ) {
  961.             /* the current context has been devastated */
  962.             emdp = NULL;            
  963.             getcontext(conns[0]);    /* set context to the first one in the table */
  964.         }
  965.         if (twp == keydp) {
  966.             /* if the context was the one on top--very likely--
  967.                 it exists no longer... */
  968.             keydp = NULL;
  969.             keywindow = NULL;
  970.         }
  971.     }
  972.     else {
  973.         /* leave one emdp struct around so
  974.             only 1 conn struct w/ no window exists */
  975.         
  976.         if (quitonclose)
  977.             /* user wants close when no windows/sessions exist */
  978.             cu_exit(0);
  979.             
  980.         connavailable = TRUE;    
  981.         setcontext(emdp);
  982.         
  983.         keydp = NULL;
  984.         keywindow = NULL;
  985.         
  986.         emedit(emdp, TRUE);
  987.         showcursor();                /* make sure cursor drawn */
  988.         /* TODO windows need to be reset and should the config be reset? */
  989.     }
  990.     --conncount;
  991.     conns[conncount] = NULL;
  992. }
  993.  
  994.  
  995. /* open a connection for a connection/window structure
  996.     must be in emdp context (using getcontext() or makeconn() )
  997. */
  998.  
  999. openconn(twp)
  1000. struct winds * twp;
  1001. {
  1002.     unsigned sock;
  1003.  
  1004. #ifdef ARPFORHOST
  1005.     if (!at_arp(fhost.u.addr))
  1006.         return(-2);
  1007. #endif
  1008.  
  1009.     if (twp->connopen)
  1010.         return;
  1011.  
  1012. #ifdef MACTCP
  1013.     if (twp->conntype == CONN_CUTCP) {
  1014.         /* force it */
  1015.         twp->conntype = CONN_MACTCP;
  1016.     }
  1017. #endif
  1018.  
  1019.     if (twp->emwindow) {
  1020.         /* fix the window and menu */
  1021.         windmenumark(twp, noMark);        /* clear any marks */
  1022.         restore25();
  1023.     }
  1024.         
  1025.     if (twp->conntype == CONN_MACTCP
  1026.             || twp->conntype == CONN_CUTCP) {
  1027.         telnetreset(twp->termtype);
  1028.     }
  1029.                 
  1030.     if (twp->conntype == CONN_MACTCP 
  1031.         || macipopen && twp->conntype == CONN_CUTCP) {
  1032.         /* coerce MacTCP configuration if Cornell already started */
  1033.         
  1034.         extern int mactcp_put();
  1035.         extern int mactcp_ex();
  1036.  
  1037.         twp->conntype = CONN_MACTCP;
  1038.         
  1039.         twp->putchar = mactcp_put;
  1040.         twp->putflush = mactcp_ex;
  1041.         
  1042.         sock = tn_sock();
  1043.         if (twp->fhost.u.addr == -1L
  1044.             || twp->fhost.u.addr == 0L) {
  1045.                 /* avoid opening sessions to broadcast address, can
  1046.                     induce Cornell AT-GW to produce telnet storms... */
  1047.             error("Can't open Telnet session to the broadcast address; please reconfigure the session address");
  1048.         }
  1049.         else {
  1050.             pr25(0, hostwait);
  1051.             mactcp_open(&twp->fhost.u.addr, twp->fhost.port, sock);
  1052.         }
  1053.     }
  1054. #ifdef DUALTCP
  1055.     else if (twp->conntype == CONN_CUTCP) {
  1056.         extern int tc_put();
  1057.         extern int tcp_ex();
  1058.  
  1059.         if (tcpemdp == NULL) {
  1060.             /* add gateway address slot */
  1061.             tcpmenu();
  1062.         }
  1063.         else {
  1064.             if (tcpemdp->connopen) {
  1065.                 error("Only one Cornell TCP session can be used at a time");
  1066.                 return(-1);
  1067.             }
  1068.         }
  1069.  
  1070.         pr25(0, hostwait);
  1071.         twp->putchar = tc_put;
  1072.         twp->putflush = tcp_ex;
  1073.         
  1074.         tcpemdp = twp;
  1075.         if (!cutcpopen) {
  1076.             if (opensettings())
  1077.                 error("Can't open 'Comet Default' document");
  1078.                 
  1079.             
  1080.             tcp_init(0, tcpopn_usr, tcpwr_usr, tcpmst_run, 
  1081.                     tcpcls_usr, tcptmo_usr, tcppr_dot, tcpbfr);
  1082.         
  1083.             cutcpopen = TRUE;
  1084.             if (! (*rnet->n_subnet)()) {
  1085.                 if (get_subnet()) {
  1086.                     /* ignore lack of gateway, assume local net */
  1087.                     ;
  1088.                 }
  1089.                 else {
  1090.                     closesettings();
  1091.                     return(-1);
  1092.                 }
  1093.             }
  1094.             closesettings();
  1095.         }
  1096.         sock = tn_sock();
  1097.         tcp_open(&twp->fhost.u.addr, twp->fhost.port, sock);
  1098.     }
  1099. #endif
  1100.     else if (twp->conntype == CONN_SERD) {
  1101.         extern int serputchar();
  1102.         extern int serputflush();
  1103.         
  1104.         twp->putchar = serputchar;
  1105.         twp->putflush = serputflush;
  1106.         
  1107.         termreset();    /* clear the old screen */
  1108.         gettermtype();
  1109.         setcontext(emdp);
  1110.         
  1111.         setibm_keymode(twp->ibm_keymode);
  1112.             /* get controls now, whereas Telnet must wait until negotiations cease */
  1113.             
  1114.         if (openserport()) {
  1115.             pr25(0, nosessionstr);
  1116.             return(-1);
  1117.         }
  1118.         opn_usr();
  1119.         emdp->tndata = TRUE;            /* guarantee controls come up */
  1120.         hostconncomplete(emdp->connmacro);
  1121.     }
  1122.     return(0);
  1123. }
  1124.  
  1125.  
  1126.  
  1127. #define DLACCEPT     2000
  1128. #define DLACYES        1
  1129. #define DLACNO        2
  1130.  
  1131. int tftp_direction;
  1132.  
  1133. tntftp(host, file, dir)
  1134.     in_name host;
  1135.     char *file;
  1136.     unsigned dir; 
  1137. {
  1138.     char buffer[100];
  1139.     char c;
  1140.     short item;
  1141.     DialogPtr dptr;
  1142.     GrafPtr oldport;
  1143.  
  1144.     tftp_direction = dir;
  1145.     if (tftpask == TFNO) {
  1146.         mac_setdownvol();
  1147.         if (dir == PUT) {
  1148.             /* save the text window if necessary */
  1149.             textupedit(file);
  1150.         }
  1151.         return(TRUE);
  1152.     }
  1153.     else if (tftpask == TFYES) {
  1154. #ifdef BACKTFTPREJECT
  1155.         if (chkbackground())
  1156.             /* if asking on & we're in the background, reject the request */
  1157.             return(FALSE);
  1158. #endif
  1159.  
  1160.         if (host == emdp->fhost.u.addr) {
  1161.             ctop(file);
  1162.             HLock(emdp->hhostname);
  1163.             ParamText(*emdp->hhostname, dir == PUT ? "\Pread" : "\Pwrite", file, "\P");
  1164.             HUnlock(emdp->hhostname);
  1165.             ptoc(file);
  1166.         }
  1167.         else {
  1168.             sprintf(buffer, "%a", host);
  1169.             ctop(buffer);
  1170.             ctop(file);
  1171.             ParamText(buffer, dir == PUT ? "\Pread" : "\Pwrite", file, "\P");
  1172.             ptoc(file);
  1173.         }
  1174.         /* do dialog to determine if user will accept */
  1175.         GetPort(&oldport);
  1176.         emwdeactivate();
  1177.         
  1178.         SetDAFont(systemFont);
  1179.         if ( ( dptr = 
  1180.             GetNewDialog(DLACCEPT, (Ptr) NULL, (WindowPtr) -1) ) == NULL )
  1181.             return(FALSE);
  1182.  
  1183.         centerwind(dptr);
  1184.         SetPort(dptr);
  1185.         SetCursor(&arrow);        /* guarantee cursor is not blank */
  1186.         itemhighlight(dptr, 1);
  1187.  
  1188.         modaldialog = TRUE;
  1189.         while (TRUE) {
  1190. #ifdef MACTCP
  1191.             ModalDialog( (ProcPtr) NULL, &item);
  1192. #else
  1193.             extern Boolean alfilter();
  1194.             ModalDialog( (ProcPtr) alfilter, &item);
  1195. #endif
  1196.             switch (item) {
  1197.                 case DLACYES: {
  1198.                     DisposDialog(dptr);
  1199.                     SetPort(oldport);
  1200.                     modaldialog = FALSE;
  1201.                     mac_setdownvol();    /* fix the directory for multiple sessions */
  1202.                     if (dir == PUT)
  1203.                         textupedit(file);
  1204.                     return(TRUE);
  1205.                 }
  1206.                 case DLACNO: {
  1207.                     DisposDialog(dptr);
  1208.                     SetPort(oldport);
  1209.                     modaldialog = FALSE;
  1210.                     return(FALSE);
  1211.                 }
  1212.             }
  1213.         }
  1214.     }
  1215. }  
  1216.  
  1217.  
  1218.  
  1219.  
  1220. /*  function called when file transfer is done.  */
  1221.  
  1222. #define ALFTOK        2001
  1223. #define ALFTFAIL    2002
  1224.  
  1225. char transok[] = "File transferred OK\r";
  1226. char transfail[] = "File transfer FAILED\r";
  1227.  
  1228. tntfdn(success) 
  1229. int    success;
  1230. {
  1231.     extern char macfile[];            /* for tftp Macintosh file name translation */
  1232.  
  1233.     if (success)  {
  1234.         if (tftp_direction == GET) {
  1235.             textdownedit(&macfile[0]);
  1236.         }
  1237.     }
  1238.     else {
  1239.         fillwindow(COPYWINDOW, transfail, (long) strlen(transfail), systemFont, 12, 0L);
  1240.     }
  1241. }
  1242.  
  1243.  
  1244.  
  1245. itemhighlight(dlog, item)
  1246. DialogPtr dlog;
  1247. int item;
  1248. {
  1249.     short itemtype;
  1250.     Handle itemhand;
  1251.     Rect itemrect;
  1252.  
  1253.     GetDItem(dlog, (short) item, &itemtype, &itemhand, &itemrect);
  1254.     PenSize(3, 3);
  1255.     InsetRect(&itemrect, -4, -4);
  1256.     FrameRoundRect(&itemrect, 16, 16);
  1257. }
  1258.  
  1259. /* check to see if we have enough memory */
  1260.  
  1261. char * memstr = "Not enough memory ";
  1262.  
  1263. long memtest(amount, usererr)
  1264. long amount;
  1265. char * usererr;
  1266. {
  1267.     long free;
  1268.     char errstr[120];
  1269.     char * errp;
  1270.     
  1271.     if ( (free = FreeMem()) < amount + 15000) {
  1272.         strcpy(&errstr[0], memstr);
  1273.         if (usererr != NULL)
  1274.             strncat(&errstr[strlen(memstr)], usererr, 80);
  1275.         prerr25(&errstr[0]);
  1276.         return(0);
  1277.     }
  1278.     else
  1279.         return(free);
  1280. }
  1281.  
  1282.  
  1283.  
  1284. #ifdef MACTCP
  1285. /* define stubs for uncalled functions */
  1286.  
  1287. tcptmo_usr() 
  1288. {
  1289. }
  1290.  
  1291.  
  1292. tcpbfr() 
  1293. {
  1294. }
  1295.  
  1296. tcppr_dot()
  1297. {
  1298. }
  1299.  
  1300.  
  1301. datayield()
  1302. {
  1303. }
  1304.  
  1305. #else
  1306. tcptmo_usr() 
  1307. {
  1308.     error("Cannot reach host");
  1309.     tcpemdp->closeflag = TRUE;
  1310.     mtevent = TRUE;
  1311. }
  1312.  
  1313.  
  1314. tcpbfr() 
  1315. {
  1316.     if (tcpemdp->ucb.u_tcpfull) {
  1317.         tcpemdp->ucb.u_tcpfull = 0;
  1318.     }
  1319. }
  1320.  
  1321. tcppr_dot()
  1322. {
  1323. }
  1324.  
  1325.  
  1326. datayield()
  1327. {
  1328.     if (rnet->n_demux->ev_flg) {
  1329.         /* input q needs service */
  1330.         tkrun = rnet->n_demux;
  1331.         tk_yield();
  1332.     }
  1333. }
  1334.  
  1335. #endif
  1336.  
  1337. /* change controls & menus to reflect terminal we are emulating */
  1338.  
  1339. ibmmode(flag)
  1340. int flag;
  1341. {
  1342.     extern int ibmproc_token();
  1343.     extern int ibmsendchar();
  1344.     extern int ibmsendstr();
  1345.  
  1346.     extern int proc_token();
  1347.     extern int asciisendchar();
  1348.     extern int asciisendstr();
  1349.  
  1350.     emdp->ibm_mode = flag;
  1351.     
  1352.     /* select the token processor for handling user input */
  1353.     if (emdp->ibm_mode) {
  1354.         emdp->dotoken = ibmproc_token;
  1355.         emdp->sendchar = ibmsendchar;
  1356.         emdp->sendstr = ibmsendstr;
  1357.         
  1358.         /* TODO we need to reset the color map if it wasn't configured ... */
  1359.     }
  1360.     else {
  1361.         emdp->dotoken = proc_token;
  1362.         emdp->sendchar = asciisendchar;
  1363.         emdp->sendstr = asciisendstr;
  1364.     }
  1365. }
  1366.  
  1367.  
  1368. /* set up the controls and key resources for the emulator type 
  1369.     TODO could be more efficient if already set...
  1370. */
  1371.  
  1372. setibm_keymode(flag)
  1373. int flag;
  1374. {
  1375.     /* fix controls */
  1376.     
  1377.     reopenconfig(emdp);
  1378.  
  1379.     if (emwindow != NULL) {
  1380.         killcontrols(emwindow);
  1381.         controlinit(emwindow, flag ? IBMRES : ASCRES);
  1382.         
  1383.         /* do menu stuff */
  1384.         if (emdp == keydp) {
  1385.             if (keymenus(emdp))
  1386.                 DrawMenuBar();
  1387.         }
  1388.     }
  1389.     
  1390.     /* fix the key resources */
  1391.     keyxrelease();
  1392.     if (!emdp->newconf)
  1393.         keyxinit();
  1394.     closeconfig(emdp);
  1395.  }
  1396.  
  1397.  
  1398.  
  1399. #define MAXCLOSERS 30
  1400. static int (*closers[MAXCLOSERS])();
  1401. static int nclosers = 0;
  1402.  
  1403. exit_hook(func)
  1404.    int (*func)();
  1405. {
  1406.     if (nclosers < MAXCLOSERS)
  1407.         closers[++nclosers] = func;
  1408.     else
  1409.         error("out of exit_hooks");
  1410. }
  1411.  
  1412. cu_exit(arg)
  1413. int arg;
  1414. {
  1415.     int count;
  1416.  
  1417.     for(count = nclosers; count; count--)
  1418.         (*closers[count])();
  1419.     exit(arg);
  1420.       
  1421. }
  1422.  
  1423.  
  1424. /*    reset output context; most routines rely on the global emdp to 
  1425.     point to the current output window.  Several per-window variables
  1426.     are maintained also as globals to reduce overhead in the emulators
  1427.     and avoid modifying old code (zap esp.) to use emdp.
  1428.     
  1429.     It is crucial that the globals be maintained properly!
  1430. */
  1431.  
  1432. getcontext(conp)
  1433. struct winds * conp;
  1434. {
  1435.     if (conp == emdp) {
  1436.         /* save some time */
  1437.         if (emwindow) {
  1438.             /* guarantee at a minimum that port is set right */
  1439.             SetPort(emwindow);
  1440.         }
  1441.         return;
  1442.     }
  1443.     savecontext(emdp);
  1444.         /* save the old global context before the change */
  1445.     setcontext(conp);
  1446. }    
  1447.  
  1448.  
  1449. /* set the globals from a winds struct; set them all, since otherwise
  1450.     there might be a failure to save stuff during Telnet negotiations */
  1451.  
  1452. setcontext(conp)
  1453. register struct winds * conp;
  1454. {
  1455.     if (conp == NULL)
  1456.         return;
  1457.         
  1458.     if (conp->emwindow) {
  1459.         emwindow = conp->emwindow;
  1460.         SetPort(emwindow);                /* guarantee port is set right */
  1461.     }
  1462.     else 
  1463.         emwindow = NULL;
  1464.     
  1465.     emdp = conp;                    /* set the major league window structure * globals */
  1466.     
  1467.     thefont = conp->thefont;                        /* default font */
  1468.     startarr = conp->startarr;                        /* dsdraw -> array of ptrs to scanline starts */
  1469.     screenbytes = conp->screenbytes;                /* width of screen in bytes */
  1470.     screenrem = conp->screenrem;                    /* screenbytes - std screen */
  1471.     fontwidth = conp->fontwidth;
  1472.     
  1473.     xpos = conp->xpos;
  1474.     ypos = conp->ypos;                                /* current x, y position */
  1475.     modflg = conp->modflg;                            /* line modified bit array */
  1476.     clrflg = conp->clrflg;                            /* line cleared bit array */
  1477.  
  1478.     /* H19 vars */
  1479.     mode = conp->mode;                            /* interpretation mode of emulator */
  1480.     charp = conp->charp;                        /* ASCII -> cursor location in charr */
  1481.     attrib = conp->attrib;                        /* normal/reverse mode for copy drawing */
  1482.  
  1483.     wrap_around = conp->wrap_around;            /* normal/reverse mode for copy drawing */
  1484.     inserton = conp->inserton;                    /* insert mode */
  1485.     linelength = conp->linelength;                /* width of row */
  1486.     lastcol = conp->lastcol;                    /* linelength - 1 */
  1487.  
  1488.     /* vt100; preceeding are h19 vars also */
  1489.  
  1490.     vtmode = conp->vtmode;                        /* new mode holder for vt100 */
  1491.     argp = conp->argp;                            /* -> current argument */
  1492.  
  1493.     /* variables important to the 3270 interpreter */
  1494.     
  1495.     cmdstate = conp->cmdstate;                    /* state of the emulator */
  1496.     scr_map = conp->scr_map;                    /* 3270 screen map */
  1497.     smap_end = conp->smap_end;                    /* end of map */
  1498.     current_attr = conp->current_attr;          /* pointer to most recent attribute */
  1499.     cursor_ptr = conp->cursor_ptr;                /* current cursor position in screen map */
  1500.     firstp = conp->firstp;                        /* ptr to first data byte processed for set_map */
  1501. }
  1502.  
  1503. /*    
  1504.     restore output context:  save the globals which may have been modified for the
  1505.     next time around with this window
  1506. */
  1507.  
  1508. savecontext(conp)
  1509. register struct winds * conp;
  1510. {
  1511.  
  1512.     if (conp == NULL) 
  1513.         return;
  1514.     
  1515.     conp->xpos = xpos;
  1516.     conp->ypos = ypos;                        /* BIGG current x, y position */
  1517.     conp->modflg = modflg;                    /* BIGG line modified bit array */
  1518.     conp->clrflg = clrflg;                    /* BIGG line cleared bit array */
  1519.     
  1520.     /* h19 */
  1521.     conp->mode = mode;                        /* BIGG interpretation mode of emulator */
  1522.     conp->inserton = inserton;                /* BIGG insert mode */
  1523.     conp->attrib = attrib;                    /* BIGG normal/reverse mode for copy drawing */
  1524.     conp->wrap_around = wrap_around;        /* BIGG normal/reverse mode for copy drawing */
  1525.     conp->charp = charp;                    /* BIGG ASCII -> cursor location in charr */
  1526.  
  1527.     conp->linelength = linelength;            /* BIGG width of row */
  1528.     conp->lastcol = lastcol;                /* BIGG linelength - 1 */
  1529.  
  1530.     /* vt100 */
  1531.     conp->vtmode = vtmode;                    /* BIGG new mode holder for vt100 */
  1532.     conp->argp = argp;                        /* BIGG -> current argument */
  1533.  
  1534.     /* 3270 */
  1535.     conp->cmdstate = cmdstate;                /* BIGG state of the emulator */
  1536.     conp->scr_map = scr_map;                /* BIGG 3270 screen map */
  1537.     conp->smap_end = smap_end;                /* BIGG end of map */
  1538.     conp->current_attr = current_attr;      /* BIGG pointer to most recent attribute */
  1539.     conp->cursor_ptr = cursor_ptr;            /* BIGG current cursor position in screen map */
  1540.     conp->firstp = firstp;                    /* BIGG ptr to first data byte processed for set_map */
  1541.  
  1542. }    
  1543.  
  1544.  
  1545. /* We check instead to see if any data has arrived and upcall if so,
  1546.     and try to send things waiting on the queue */
  1547.  
  1548. short inio_service;
  1549.  
  1550. io_service()
  1551. {
  1552.     struct winds ** conp = conns;
  1553.     struct winds * conend = &conp[conncount];
  1554.     register struct winds * twp;
  1555.     int serialtime;
  1556.     
  1557.     if (inio_service)
  1558.         return;
  1559.     inio_service = TRUE;
  1560.     
  1561.     if (tickserial && cticks >= tickserial)
  1562.         serialtime = TRUE;
  1563.     else 
  1564.         serialtime = FALSE;
  1565.         
  1566.     /*  go through window list to see who needs service */
  1567. #ifdef TFTPSERVE
  1568.     if (tfsdata || tftpdata)
  1569.         /* MacTCP tftp service */
  1570.         tftp_upcall();
  1571. #endif
  1572.  
  1573.     if (mtevent) {
  1574.         mtevent = FALSE;        /* reset immediately after test: set asynchronously */
  1575.     }
  1576.     else if (serialtime) {
  1577.         tickserial = cticks + serialwait;
  1578.     }
  1579.     else {
  1580.         /* nothing happening, try to save time */
  1581.         inio_service = FALSE;
  1582.         return;
  1583.     }
  1584.     
  1585.     while (conp < conend) {
  1586.         twp = *conp++;
  1587.         if (twp == NULL)
  1588.             continue;
  1589.                 
  1590. #ifdef MAKEHYCCONN    
  1591.         if (twp->hycconnwait == TRUE) {
  1592.             /* if the API has requested an open, do it */
  1593.             /* use macro ? */
  1594.             twp->hycconnwait = 1;
  1595.             if (makeconn()) {
  1596.                 killconn();
  1597.                 continue;
  1598.             }
  1599.             getconfig();
  1600.             emdp->resfid = appresfid;
  1601.             emdp->resvol = appvol;
  1602.             emdp->resdir = appdir;
  1603.             
  1604.             keyxinit();
  1605.             makewind();
  1606.             openconn(emdp);
  1607.             continue;
  1608.         }
  1609. #endif
  1610.         if (twp->conntype == CONN_MACTCP) {
  1611.             /* has no new data... */
  1612.              if (! (twp->data_rcvd || twp->closeflag || twp->send_wait))
  1613.                 continue;
  1614.  
  1615.             /* reset output context */
  1616.             getcontext(twp);
  1617.             
  1618.             if (twp->data_rcvd) {
  1619.                 tcp_upcall();
  1620.                 twp->modflg = modflg;
  1621.                     /* update; could use savecontext() but not only modflg needed */
  1622.             }
  1623. #ifdef ASYNCOPEN
  1624.             if (!modaldialog && twp->openflag) {
  1625.                 opn_usr();
  1626.             }
  1627. #endif
  1628.             if (!modaldialog && twp->closeflag) {
  1629.                 /* don't EVER do this in the background, cls_usr may dialog */
  1630.                 mactcp_wrapup();    /* WARNING: twp may disappear, emdp may change! */
  1631.             }
  1632.             if (twp->send_wait) {
  1633.                 /* a packet is waiting for buffer; try to send again */
  1634.                 mactcp_ex();
  1635.             }
  1636.             else if (twp->fillcount && (twp->fillcount == twp->waitcount)) {
  1637.                 /* SHOULD NEVER REACH THIS POINT! symptom of 
  1638.                     MacTCP async "let's waste some variables" behavior */
  1639.                 prerr25("send_wait clobbered");
  1640.                 mactcp_ex();
  1641.             }
  1642.             continue;
  1643.         }
  1644. #ifdef DUALTCP
  1645.         else if (twp->conntype == CONN_CUTCP) {
  1646.             if (!modaldialog && twp->closeflag) {
  1647.                 /* close the session */
  1648.                 /* don't EVER do this in the background, cls_usr may dialog */
  1649.                 twp->closeflag = FALSE;
  1650.                 getcontext(twp);
  1651.                 windmenumark(twp, noMark);        /* clear any marks */
  1652.                 cls_usr();            /* WARNING: twp may disappear, emdp may change! */
  1653.             }
  1654.             continue;
  1655.         }
  1656. #endif
  1657.         else if (twp->conntype == CONN_SERD && serialtime) {
  1658.             /* check for serial data */
  1659.  
  1660.             getcontext(twp);
  1661.             serial_service();
  1662.             twp->modflg = modflg;
  1663.             continue;
  1664.         }
  1665.         else if (twp->conntype == CONN_COMMMGR) {
  1666.                 /* check for comm mgr data */
  1667.             ;
  1668.             continue;
  1669.         }
  1670.     }
  1671.     inio_service = FALSE;
  1672. }
  1673.  
  1674.  
  1675.  
  1676. nullputchar()
  1677. {
  1678. }
  1679.  
  1680. nullputflush()
  1681. {
  1682. }
  1683.  
  1684.  
  1685. /* called in the main user task to serve I/O while in dialog 
  1686.     or other modal situation */
  1687.  
  1688. bkrd_service()
  1689. {
  1690.     struct winds * oemdp;
  1691.     GrafPtr oport;
  1692.     
  1693.     oemdp = emdp;
  1694.     GetPort(&oport);
  1695.     
  1696.     token_service();    /* user output--handle actions waiting on the queue */
  1697.     io_service();        /* for merged MacTCP/CUTCP */
  1698. #ifdef DUALTCP
  1699.     tk_yield();            /* task yield for Cornell TCP */
  1700. #endif
  1701.     screen_service();    /* update screen */
  1702.     
  1703.     if (emdp != oemdp)
  1704.         /* restore the old context for all the callers out there */
  1705.         getcontext(oemdp);
  1706.     
  1707.     if (oport)
  1708.         SetPort(oport);     /* might not be emwindow */
  1709. }
  1710.  
  1711.  
  1712. /* turn the tftp server on
  1713. */
  1714.  
  1715. #define    OFF    0
  1716. #define    ON    1
  1717.  
  1718. tfs_on() 
  1719. {
  1720.     extern short tfstate;
  1721.  
  1722.     if (!tftpopen) {
  1723.         if (emdp->conntype == CONN_MACTCP) {
  1724.             if (mtcp_tfsinit(tntftp, tntfdn))
  1725.                 return(FALSE);
  1726.             tftpopen = TRUE;
  1727.         }
  1728. #ifdef DUALTCP
  1729.         else if (emdp->conntype == CONN_CUTCP) {
  1730.             if (tfsinit(tntftp, tntfdn))
  1731.                 return(FALSE);
  1732.             tftpopen = TRUE;
  1733.         }
  1734. #endif
  1735.     }
  1736.     tfstate = ON;
  1737.     return(TRUE);
  1738. }
  1739.  
  1740. /* turn the tftp server off
  1741. */
  1742.  
  1743. tfs_off() 
  1744. {
  1745.     extern short tfstate;
  1746.  
  1747.     tfstate = OFF;
  1748. }
  1749.  
  1750.  
  1751. /* set the name in the appfile struct used for document naming control */
  1752.  
  1753. setappfilename()
  1754. {
  1755.     register char * chp;
  1756.     register char * endp;
  1757.     register char * destp;
  1758.  
  1759.     /* copy the name into the appfile struct from hhostname;
  1760.         hhostname is a Pascal string */
  1761.     chp = *emdp->hhostname;
  1762.     endp = chp + **emdp->hhostname + 1;
  1763.     destp = &emdp->appfile.fName;
  1764.     
  1765.     while (chp < endp) {
  1766.         *destp++ = *chp++;
  1767.     }
  1768. }
  1769.  
  1770.  
  1771. istcptype()
  1772. {
  1773.     if (emdp->conntype == CONN_SERD || emdp->conntype == CONN_COMMMGR)
  1774.         return(FALSE);
  1775.     else
  1776.         return(TRUE);
  1777. }
  1778.  
  1779.  
  1780. /* added for compatibility with MPW */
  1781.  
  1782. SwapMMUMode(chararg)
  1783. Byte * chararg;
  1784. {
  1785. #asm
  1786.     move.l    8(a6),a0                    ; -> byte arg
  1787.     move.b    (a0),d0                        ; d0 = arg
  1788.     dc.w    $a05d                        ; _SwapMMUMode
  1789.     move.b    d0,(a0)                        ; return current mode in arg
  1790. #endasm
  1791. }
  1792.  
  1793. #ifndef DUALTCP
  1794.  
  1795. tcp_close()
  1796. {
  1797. }
  1798.  
  1799. DialogPtr nnrdptr;
  1800.  
  1801. shownnr()
  1802. {
  1803. }
  1804.  
  1805. hidennr()
  1806. {
  1807. }
  1808.  
  1809. #endif
  1810.  
  1811.  
  1812. invalidconn(twp)
  1813. struct winds * twp;
  1814. {
  1815.     register short count = 0;
  1816.     
  1817.     for (count = 0; count < conncount; count++) {
  1818.         if (twp == conns[count])
  1819.             return(0);
  1820.     }
  1821.     /* no such connection exists */
  1822.     return(-1);
  1823. }